package com.example.androidaudiovideodemo

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.opengl.GLES20
import android.opengl.GLSurfaceView
import android.opengl.GLUtils
import android.opengl.Matrix
import android.util.Log
import java.lang.RuntimeException
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

/**
 *
 * author: renbing
 *
 * date: 2022/1/26
 *
 * des:绘制图片纹理的renderer
 */
class ImageTextureRenderer(val context: Context) : GLSurfaceView.Renderer{

    private val VERTEX_SHADER = "attribute vec4 vPosition;" +
            "attribute vec2 vCoordinate;" +
            "varying vec2 aCoordinate;" +
            "void main() {" +
            "    gl_Position = vPosition;" +
            "    aCoordinate = vCoordinate;" +
            "}"

    private val FRAGMENT_SHADER = "precision mediump float;" +
            "uniform sampler2D vTexture;" +
            "varying vec2 aCoordinate;" +
            "void main() {" +
            "    gl_FragColor = texture2D(vTexture,aCoordinate);" +
            "}"

    private val vertex = floatArrayOf(
        -1f,1f,
        -1f,-1f,
        1f,1f,
        1f,-1f
    )

    private val sCoord = floatArrayOf(
        0f,0f,
        0f,1f,
        1f,0f,
        1f,1f
    )

    private var mVertexBuffer: FloatBuffer? = null
    private var mFragmentBuffer: FloatBuffer? = null

    private var mProgram = 0
    private var mVPosition = 0
    private var mVCoordinate = 0
    private var mVTexture = 0
    private var mTextureId = 0

    private var mWidth = 0
    private var mHeight = 0
    private var mProjectMatrix = FloatArray(16)
    private var mViewMatrix = FloatArray(16)
    private var mMVPMatrix = FloatArray(16)

    init {
        mVertexBuffer = ByteBuffer.allocateDirect(vertex.size*4).order(ByteOrder.nativeOrder()).asFloatBuffer()
        mVertexBuffer?.run {
            //放置数据  否则不显示
            put(vertex)
            position(0)
        }

        mFragmentBuffer = ByteBuffer.allocateDirect(sCoord.size*4).order(ByteOrder.nativeOrder()).asFloatBuffer()
        mFragmentBuffer?.run {
            put(sCoord)
            position(0)
        }
    }

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        //创建顶点着色器和片元着色器
        val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,VERTEX_SHADER)
        val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,FRAGMENT_SHADER)

        //创建一个空程序
        mProgram = GLES20.glCreateProgram()
        //绑定着色器
        GLES20.glAttachShader(mProgram,vertexShader)
        GLES20.glAttachShader(mProgram,fragmentShader)
        //生成一个可执行的程序
        GLES20.glLinkProgram(mProgram)

        val linkStatus = IntArray(1)
        GLES20.glGetProgramiv(mProgram,GLES20.GL_LINK_STATUS,linkStatus,0)
        if (linkStatus[0] != GLES20.GL_TRUE){
            val info = GLES20.glGetProgramInfoLog(mProgram)
            GLES20.glDeleteProgram(mProgram)
            throw RuntimeException("Could not link program: $info")
        }

        mVPosition = GLES20.glGetAttribLocation(mProgram,"vPosition")
        mVCoordinate = GLES20.glGetAttribLocation(mProgram,"vCoordinate")
        mVTexture = GLES20.glGetUniformLocation(mProgram,"vTexture")

        mTextureId = loadTexture(R.drawable.icon_test)

    }

    /**
     * 加载着色器
     */
    private fun loadShader(type: Int,vertexShader: String): Int{
        //根据type创建着色器
        val glCreateShader = GLES20.glCreateShader(type)
        //加载资源
        GLES20.glShaderSource(glCreateShader,vertexShader)
        //编译
        GLES20.glCompileShader(glCreateShader)
        val compiled = IntArray(1)
        GLES20.glGetShaderiv(glCreateShader,GLES20.GL_COMPILE_STATUS,compiled,0)
        if (compiled[0] != GLES20.GL_TRUE){
            GLES20.glDeleteShader(glCreateShader)
            return -1
        }
        return glCreateShader
    }

    /**
     * 加载纹理
     */
    private fun loadTexture(resId: Int): Int{
        val textures = IntArray(1)
        //创建纹理
        GLES20.glGenTextures(1,textures,0)
        //绑定纹理
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textures[0])
        //激活第0个纹理
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
        GLES20.glUniform1i(mVTexture,0)
        //设置环绕和过滤方式
        //环绕（超出纹理坐标范围）： （s==x t==y）
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_REPEAT)
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_REPEAT)
        //过滤 （纹理像素映射到坐标点）：（缩小、放大：GL_LINEAR 线性）
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR)
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR)

        var bitmap = BitmapFactory.decodeResource(context.resources,resId)
        mWidth = bitmap?.width?:0
        mHeight = bitmap?.height?:0
        Log.e("TAG","bitmap_width:${bitmap?.width}")
        Log.e("TAG","bitmap_height:${bitmap?.height}")
        //设置图片
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D,0,bitmap,0)
        bitmap?.recycle()
        bitmap = null
        //解绑纹理
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,0)
        return textures[0]
    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        Log.e("TAG","onSurfaceChanged_width:$width")
        Log.e("TAG","onSurfaceChanged_height:$height")
        GLES20.glViewport(0,0,width, height)

        val sWH = mWidth.toFloat().div(mHeight.toFloat())
        val sWidthHeight = width.toFloat().div(height.toFloat())
        if (width>height){
            if (sWH>sWidthHeight){
                Matrix.orthoM(mProjectMatrix,0,-sWidthHeight*sWH.toFloat(),sWidthHeight*sWH.toFloat(),-1f,1f,3f,7f)
            }else{
                Matrix.orthoM(mProjectMatrix,0,-sWidthHeight/sWH.toFloat(),sWidthHeight/sWH.toFloat(),-1f,1f,3f,7f)
            }
        }else{
            if (sWH>sWidthHeight){
                Matrix.orthoM(mProjectMatrix,0,-1f,1f,-1/sWidthHeight*sWH.toFloat(),1/sWidthHeight*sWH.toFloat(),3f,7f)
            }else{
                Matrix.orthoM(mProjectMatrix,0,-1f,1f,-sWH/sWidthHeight.toFloat(),sWH/sWidthHeight.toFloat(),3f,7f)
            }
        }
        Matrix.setLookAtM(mViewMatrix,0,0f,0f,7f,0f,0f,0f,0f,1f,0f)
        Matrix.multiplyMM(mMVPMatrix,0,mProjectMatrix,0,mViewMatrix,0)
    }

    override fun onDrawFrame(gl: GL10?) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
        GLES20.glClearColor(1f,0f,0f,1f)
        //使用程序
        GLES20.glUseProgram(mProgram)
        //绑定纹理
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,mTextureId)
        //使顶点属性数组有效
        GLES20.glEnableVertexAttribArray(mVPosition)
        //为顶点属性赋值
        GLES20.glVertexAttribPointer(mVPosition,2,GLES20.GL_FLOAT,false,8,mVertexBuffer)

        //使片元属性数组有效
        GLES20.glEnableVertexAttribArray(mVCoordinate)
        GLES20.glVertexAttribPointer(mVCoordinate,2,GLES20.GL_FLOAT,false,8,mFragmentBuffer)
        //绘制
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP,0,4)
        //解除绑定
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,0)
    }
}